package com.example.demo.study.genericity;

import java.util.*;

public class Test {
    public static <T> void t(T x) {
        System.out.println(x.getClass().getName());
    }

    public static <K,V> Map<K, V> newMap() {
        return new HashMap<K, V>();
    }

    /**
     * 使用泛型方法时不用显示的指定出具体的类型，编译器会根据方法类型参数的
     * 入参或返回赋值的类型推断出具体的类型，但若将调用结果直接作为一个参数传递给另外一个方法，
     * 这时编译器并不会进行类型推断。如果是基本类型则会自动装箱为包装类型。
     * @param v
     * @return
     * @param <T>
     */
    public static <T> String className(T v) {
        return v.getClass().getSimpleName();
    }

    /**
     * 变长参数列表也可以使用泛型参数:
     * @param args
     * @return
     * @param <T>
     */
    public static <T> List<T> toList(T... args) {
        List<T> l = new ArrayList<T>(args.length);
        for (T e : args) {
            l.add(e);
        }
        return l;
    }

    public static <T> T[] toArray(T... args) {
        return args;
    }


    public static void main(String[] args) {
        t(11);
        t("abc");
//        Map<String, Date> m = newMap();
        Map<String, Date> m = Test.<String, Date>newMap();
        m.put("now",new Date());
        System.out.println(m);

        System.out.println(Test.className(11));

        /**
         * 当调用一个可变参数方法时，会创建一个数组来存放可变参数，若参数的类型是泛型的，那么将创建泛型的数组，但Java不是允许直接使用泛型创建数组吗？
         * 这里java做了一些妥协允许为可变参数创建一个泛型数组。但可变参数列表的入参是可以为不同类型的，所以有时编译也无法决定泛型可变参数的具体类型，只能选择一个最通用的类型。
         */
        System.out.println(toArray(Integer.valueOf(11),   Double.valueOf(13)).getClass());
    }
}
